package com.meatball.dji.common.mqtt

import com.meatball.dji.common.mqtt.router.MqttMessageRouter
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken
import org.eclipse.paho.client.mqttv3.MqttCallback
import org.eclipse.paho.client.mqttv3.MqttClient
import org.eclipse.paho.client.mqttv3.MqttMessage
import org.slf4j.LoggerFactory

/**
 * TODO mqtt消息回调
 *
 * @author 张翔宇
 * @since 2024年4月17日
 */
class PushCallback(
    private val mqttMessageRouter: MqttMessageRouter,
    private val mqttClient: MqttClient
) : MqttCallback {
    companion object {
        private val logger = LoggerFactory.getLogger(PushCallback::class.java)
    }

    /**
     * TODO 在连接丢失时调用此方法
     *
     * @param cause 异常原因
     */
    override fun connectionLost(cause: Throwable?) {
        // 连接丢失后，一般在这里面进行重连
        logger.info("断开连接，可以重新连接。")
    }

    /**
     * TODO 当收到服务器的消息时，会调用此方法
     *
     * @param topic 消息主题
     * @param message 消息内容
     */
    override fun messageArrived(topic: String?, message: MqttMessage?) {
        // subscribe后得到的消息会执行到这里面
        logger.info("接收消息主题：$topic")
        logger.info("接收到消息Qos：${message?.qos}")

        val topicContainsOsd = topic?.contains("osd") == true
        val topicContainsState = topic?.contains("state") == true

        if (message != null && topic != null) {
            val msg = message.payloadAsString
            logger.info("接收消息内容：$msg")
            when {
                topicContainsOsd -> {
                    mqttMessageRouter.osdMessage(topic, msg, mqttClient)
                }
                topicContainsState -> {

                }
                else -> {
                    val methodName = extractMethodNameFromMessage(msg)
                    mqttMessageRouter.routeMessage(methodName, msg, mqttClient)
                }
            }
        }
    }

    /**
     * TODO 当交付令牌完成时，会调用此方法
     *
     * @param token 传送消息的标记
     */
    override fun deliveryComplete(token: IMqttDeliveryToken?) {
        logger.info("消息投递完成，令牌为：${token?.response}")
    }

    /**
     * TODO 解析出方法的名称
     *
     * @param message 消息内容
     * @return 具体方法名称
     */
    private fun extractMethodNameFromMessage(message: String): String {
        val regex = """"method"\s*:\s*"(.+?)"""".toRegex()
        val matchResult = regex.find(message)

        val method = matchResult?.groups?.get(1)?.value
        if (method != null) {
            return method
        }
        logger.error("JSON格式不正确，请检查：$message")
        return ""
    }

    /**
     * 扩展函数，用于获取 MqttMessage 的消息内容字符串表示
     */
    private val MqttMessage.payloadAsString: String
        get() = String(payload, Charsets.UTF_8)
}